<template>
  <div>
    <PDFBox ref="pdfRef"></PDFBox>
    <MdBox ref="mdRef"></MdBox>
    <ImageBox ref="imageBoxRef" :images="images"></ImageBox>
    <VideoBox ref="videoRef"></VideoBox>
    <n-data-table
        :columns="columns"
        :data="data"
        :bordered="false"
        :row-key="(row:any) => row.key"
        :row-props="rowProps"
        :checked-row-keys="selectedRow"

        @update:checked-row-keys="handleCheck"
    />
    <n-dropdown
        placement="bottom-start"
        trigger="manual"
        :x="x"
        :y="y"
        :options="options"
        :show="showDropdown"
        :on-clickoutside="onClickoutside"
        @select="handleSelect"
    ></n-dropdown>
  </div>
</template>

<script setup lang="ts">
import {computed, h, nextTick, ref} from "vue";
import {NButton} from 'naive-ui'
import {useFileStore} from "@/store/file";
import {storeToRefs} from "pinia";
import api from "@/api";
import FileNameRow from "@/components/table/FileNameRow.vue";
import dayjs from '@/utils/dayjs'
import {getFileType, sizeUnitConvert} from "@/utils";
import {useUserStore} from "@/store/user";
import ImageBox from "@/components/box/ImageBox.vue";
import VideoBox from "@/components/box/VideoBox.vue";
import MdBox from "@/components/box/MdBox.vue";
import PDFBox from "@/components/box/PDFBox.vue";


const props = defineProps({
  data: {
    type: Array,
    default: () => []
  },
  selectedRow: {
    type: Array,
    default: () => []
  }
})
const pdfRef = ref()
const mdRef = ref()
const videoRef = ref()
const images = computed(() => {
  return props.data.filter((item: any) => {
    return item.size && (getFileType(item.name) === 'jpg' || getFileType(item.name) === 'png' || getFileType(item.name) === 'gif')
  }).map((item: any) => item.path)
})
const imageBoxRef = ref()
const emits = defineEmits(['handleGetList', 'update:selectedRow'])
const fileStore = useFileStore()
const {parentId, pathName, idPath} = storeToRefs(fileStore)
const userStore = useUserStore()
const {token} = storeToRefs(userStore);

const showDropdown = ref(false)
const x = ref(0)
const y = ref(0)
const options = ref([
  {label: '打开', key: 'open'},
  {label: '下载', key: 'download'},
  {label: '重命名', key: 'rename'},
  {label: '删除', key: 'remove'},
])
const columns = ref([
  {
    type: 'selection',
    align: 'center',
    width: 2,
  },
  {
    title: '文件名',
    key: 'name',
    width: 10,
    ellipsis: {tooltip: true},
    align: 'left',
    render(row: IFileInfo) {
      return h(FileNameRow, {row: row, onDblclick: () => handleOpen(row), onEditFinish: editNameFinish}, '')
    }
  },
  {
    title: '大小',
    key: 'size',
    width: 5,
    ellipsis: {tooltip: true},
    align: 'center',
    render(row: any) {
      return h('span', {}, row.size ? sizeUnitConvert(row.size) : '-',)
    }
  },
  {
    title: '修改日期',
    key: 'createdAt',
    width: 5,
    ellipsis: {tooltip: true},
    align: 'center',
    render(row: any) {
      return h('span', {}, row.updatedAt ? dayjs(row.updatedAt).format('YYYY-MM-DD HH:mm') : '-')
    }
  },
  {
    title: '操作', key: 'actions', width: 6, align: 'center',
    render(row: any) {
      return [
        h(NButton, {
          round: true,
          secondary: true,
          size: 'tiny',
          type: "success",
          onClick: () => handleOpen(row)
        }, {default: () => "打开"}),
        h(NButton, {
          round: true,
          secondary: true,
          size: 'tiny',
          type: "warning",
          onClick: () => handleRename(row)
        }, {default: () => "重命名"}),
        h(NButton, {
          round: true,
          secondary: true,
          size: 'tiny',
          type: "tertiary",
          onClick: () => handleDownload(row)
        }, {default: () => "下载"}),
        h(NButton, {
          round: true,
          secondary: true,
          size: 'tiny',
          type: "error",
          onClick: () => handleRemove(row)
        }, {default: () => "删除"})
      ]
    }
  }

])
/**
 * 打开
 * @param row
 */
const handleOpen = (row: any) => {
  if (row.isEdit) {
    return
  }
  if (row.size) {
    if (getFileType(row.name) === 'jpg' || getFileType(row.name) === 'png' || getFileType(row.name) === 'gif') {
      let idx = images.value.findIndex((item: any) => item === row.path)
      imageBoxRef.value.doShow(idx)
    } else if (getFileType(row.name) === 'mp4') {
      videoRef.value.doShow(row.path)
    } else if (getFileType(row.name) === 'md') {
      mdRef.value.doShow(row.id)
    } else if (getFileType(row.name) === 'pdf') {
      pdfRef.value.doShow(row.path + '?Authorization=' + token.value)
    } else {
      window.open(row.path + '?Authorization=' + token.value);
    }


  } else {
    parentId.value = row.id
    pathName.value = pathName.value + '/' + row.name
    idPath.value = idPath.value + '/' + row.id
    emits('handleGetList')
  }
  emits('update:selectedRow', [])
}

/**
 * 重命名
 * @param row
 */
const handleRename = (row: any) => {
  row.isEdit = true
  emits('update:selectedRow', [row.key])

}
const editNameFinish = (row: any, newName: string) => {
  if (row.name === newName || newName === '') {
    return
  }
  let flag = false
  props.data?.forEach((item: any) => {
    if (item.name === newName && item.id !== row.id) {
      window.$message.warning('文件名已存在')
      flag = true
    }
  })
  if (flag) {
    return
  }
  if (row.size) {
    api.file.rename({
      id: row.id,
      parentId: row.parentId,
      newName: newName
    }).then(res => {
      if (res.data.code === 0) {
        window.$message.success('重命名成功')
        row.name = newName
        row.updatedAt = dayjs().format('YYYY-MM-DD HH:mm')
      }
    })
  } else {
    api.folder.rename({
      id: row.id,
      parentId: row.parentId,
      newName: newName
    }).then(res => {
      if (res.data.code === 0) {
        window.$message.success('重命名成功')
        row.name = newName
        row.updatedAt = dayjs().format('YYYY-MM-DD HH:mm')
      }
    })
  }
}
const handleDownload = (row: any) => {
  emits('update:selectedRow', [])
  if (row.size) {
    window.$loadingBar.start()
    api.file.download({
      id: row.id
    }).then(res => {
      if (res.data.type === 'application/octet-stream') {
        let filename = decodeURI(res.headers['content-disposition']).match(/filename="([^"]+)"/)![1]
        let url = window.URL.createObjectURL(res.data)
        let a = document.createElement('a')
        a.style.display = 'none'
        a.href = url
        a.setAttribute('download', filename)
        document.body.appendChild(a)
        a.click() //执行下载
        window.$message.success(row.name + '  文件下载成功')
        window.URL.revokeObjectURL(a.href)
        document.body.removeChild(a)
      }
    }).finally(() => {
      window.$loadingBar.finish()
    })
  } else {
    window.$loadingBar.start()
    api.folder.download({
      id: row.id
    }).then(res => {
      if (res.data.type === 'application/octet-stream') {
        let filename = decodeURI(res.headers['content-disposition']).match(/filename="([^"]+)"/)![1]
        let url = window.URL.createObjectURL(res.data)
        let a = document.createElement('a')
        a.style.display = 'none'
        a.href = url
        a.setAttribute('download', filename)
        document.body.appendChild(a)
        a.click() //执行下载
        window.$message.success(row.name + '  文件下载成功')
        window.URL.revokeObjectURL(a.href)
        document.body.removeChild(a)
      }
    }).finally(() => {
      window.$loadingBar.finish()
    })
  }
}
/**
 * 删除文件
 * @param row
 */
const handleRemove = (row: any) => {
  emits('update:selectedRow', [row.key])
  window.$dialog.warning({
    title: '提示',
    content: '确定要删除选中的文件吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      remove(row)
      emits('update:selectedRow', [])
    }
  })
}

const remove = (row: any) => {
  if (row.size) {
    api.file.remove({
      id: row.id
    }).then(res => {
      if (res.data.code === 0) {
        window.$message.success('删除成功')
        emits('handleGetList')
      }
    })
  } else {
    api.folder.remove({
      id: row.id
    }).then(res => {
      if (res.data.code === 0) {
        window.$message.success('删除成功')
        emits('handleGetList')
      }
    })
  }

}
/**
 * 多选
 * @param rowKeys
 */
const handleCheck = (rowKeys: any) => {
  emits('update:selectedRow', rowKeys)
}

const rowProps = (row: any) => {
  return {
    onContextmenu: (e: MouseEvent) => {
      const baseOptions = [
        {label: '打开', key: 'open'},
        {label: '下载', key: 'download'},
        {label: '重命名', key: 'rename'},
        {label: '删除', key: 'remove'},
      ];
      options.value = props.selectedRow.length > 1
          ? baseOptions.filter(option => ['download', 'remove'].includes(option.key))
          : baseOptions;

      if (props.selectedRow?.findIndex((item: any) => item === row.key) === -1) {
        emits('update:selectedRow', [row.key])
      }
      e.preventDefault()
      showDropdown.value = false
      nextTick().then(() => {
        showDropdown.value = true
        x.value = e.clientX
        y.value = e.clientY
      })
    }
  }
}
/**
 * 右键菜单选择
 */
const handleSelect = (key: any) => {
  showDropdown.value = false
  let list = props.data.filter((option: any) => props.selectedRow.includes(option.key))
  if (key === 'open') {
    handleOpen(list[0])
  } else if (key === 'remove') {
    doRemove()
  } else if (key === 'rename') {
    handleRename(list[0])
  } else if (key === 'download') {
    doDownload()
  }
}
const onClickoutside = () => {
  showDropdown.value = false
  emits('update:selectedRow', [])
}


const doDownload = () => {
  let list = props.data.filter((option: any) => props.selectedRow.includes(option.key))
  window.$dialog.warning({
    title: '提示',
    content: '确定要下载选中的文件吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      list.forEach((item: any) => {
        handleDownload(item)
      })
    }
  })

}
const doRemove = () => {
  let list = props.data.filter((option: any) => props.selectedRow.includes(option.key))
  window.$dialog.warning({
    title: '提示',
    content: '确定要删除选中的文件吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      list.forEach((item: any) => {
        remove(item)
      })
      emits('update:selectedRow', [])
    }
  })

}
const doRename = () => {
  let index: number = props.selectedRow[0] as number
  let tmp: any = props.data?.at(index)
  tmp.isEdit = true
}
defineExpose({
  doDownload,
  doRemove,
  doRename
})
</script>

<style scoped>


</style>